<script setup lang="ts" generic="T">
import type { FormItemRule } from 'element-plus'
import type { DataFormField } from '.'
import { computed, watch } from 'vue'

const { field, data, rowIndex } = defineProps<{
  field: DataFormField
  data: any
  rowIndex?: number
  parentProp?: string
  showTitle?: 'true' | 'false'
}>()

const model = defineModel<any>()
const rules = computed(() => {
  const itemRules: FormItemRule[] = []
  if (field.require !== undefined && field.require) {
    if (field.dict !== undefined || field.options !== undefined) {
      itemRules.push({ required: true, message: `请选择${field.title}`, trigger: ['blur', 'change'] })
    }
    else {
      itemRules.push({ required: true, message: `请输入${field.title}`, trigger: ['blur', 'change'] })
    }
  }
  if (field.minLength !== undefined) {
    itemRules.push({ min: field.minLength, message: `${field.title}长度最小${field.maxLength}`, trigger: ['blur', 'change'] })
  }
  if (field.maxLength !== undefined) {
    itemRules.push({ max: field.maxLength, message: `${field.title}长度最大${field.maxLength}`, trigger: ['blur', 'change'] })
  }
  if (field.pattern !== undefined) {
    itemRules.push({ pattern: field.pattern, message: `${field.title}格式错误`, trigger: ['blur', 'change'] })
  }
  if (field.type === 'number') {
    itemRules.push({ type: 'number', message: `${field.title}必须是数字`, trigger: ['blur', 'change'] })
  }

  if (field.validator !== undefined) {
    itemRules.push({
      validator: (_, value, callback) => {
        const error = field.validator!(value)
        if (error !== undefined) {
          callback(new Error(error))
        }
        else {
          callback()
        }
      },
      trigger: 'blur',
    })
  }
  return itemRules
})

const disabled = computed(() => {
  return typeof field.edit === 'function' ? !field.edit(data, rowIndex) : (field.edit === false)
})

watch(
  () => model.value,
  (value) => {
    if (field.change) {
      field.change(value, data)
    }
  },
)
</script>

<template>
  <div class="data-form-item">
    <el-form-item
      :label="field.title"
      :prop="parentProp === undefined ? `${field.name}` : `${parentProp}.${field.name}` "
      :rules="rules"
    >
      <template #label="{ label }">
        {{ showTitle === 'false' ? '' : label }}
      </template>
      <div class="w-full">
        <slot>
          <data-select
            v-if="(field.dict !== undefined || field.options !== undefined)"
            v-model="model"
            :dict="typeof field.dict === 'string' ? { dictCode: field.dict } : field.dict"
            :options="field.options"
            :placeholder="field.placeholder"
            :disabled="disabled"
            :check-strictly="field.checkStrictly"
            :edit-type="field.editType"
          />

          <template v-else-if="field.editType === 'icon'">
            <icon-select v-model="model" />
          </template>

          <template v-else-if="field.editType === 'operator'">
            <operator-select v-model="model" />
          </template>

          <el-date-picker
            v-else-if="field.type === 'date' || field.type === 'datetime'"
            v-model="model"
            style="width: 100%;"
            :type="field.type"
            :value-format="field.type === 'date' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'"
            :placeholder="field.placeholder"
            :disabled="disabled"
          />

          <template v-else-if="field.type === 'number'">
            <el-input-number
              v-if="field.editType === 'number'"
              v-model="model" clearable :placeholder="field.placeholder" :disabled="disabled"
              :min="field.minValue" :max="field.maxValue"
            />
            <el-input
              v-else
              v-model.number="model" clearable :placeholder="field.placeholder" :disabled="disabled"
            />
          </template>

          <el-switch v-else-if="field.type === 'boolean' " v-model="model" />

          <el-input
            v-else v-model.trim="model"
            clearable :placeholder="field.placeholder" :disabled="disabled"
          />
        </slot>

        <el-alert
          v-if="field.tip "
          :title="field.tip" type="warning" :closable="false"
        />
      </div>
    </el-form-item>
  </div>
</template>

<style lang="css" scoped>
.data-form-item {
  --at-apply: m-2;
}
.data-form-item :deep(.el-alert__title) {
  --at-apply: text-xs;
}
.data-form-item .el-alert {
  --at-apply: p-1 flex-;
}
.data-form-item .el-form-item {
  --at-apply: m-0;
}

.data-form-item :deep(.el-form-item__error) {
  --at-apply: static;
}
</style>
